import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.zip.Inflater;

/**
 * 完整验证SO包加密逻辑
 * 基于libsmsdk.so.c的源代码分析，一步一步复刻加密流程
 */
public class CompleteVerification {
    
    // 真实数据（来自加密数据.md）
    private static final String EP_BASE64 = "qt0AJsNLEfayUx7S15jLfmQvMOpW6JJ+jCoxeXxn676R2OiN6xpLIQWSYe8ETFUF4+AaGrVY1wMCdyUPVaHM0J+8m+q/PUFgbiP3N8xSKQc4lIzzZuckbybYiFuLbEhcblmy162S5B70UJxzB6grhIVpsG/h0uw+JPaS2yTPpPVCiN/SImdOw2g12cun6niAwRZSQktZikzzbjwkRoiO8ehrwlAFJircnT1/1zba2oaGXLc/yU6cM2vWgJdyyoXJF4Mo/5XNBTDT+8yr1hPC5MKHWcTBB/isrRTD5CczInLgXHl48KKz18GkpPM7MML1GHb4pIjfTvu8hv/SLLW0sg==";
    private static final String DATA_BASE64 = "wHBy2LDIay6WCgEybO8bw/5OxmVd4N++OJpwr/Tgjw+TA8iZ4HAy4bN8UWtwmeGz+dqU/zX6myCireq+q465rqUqpXLhma2aEPqTaNvUTv/Y71kVpkMBkgrjMnVkIi/iBV5eKsrTPfLWO8bt0mSbLM8ghswC2m2YRInkqWXHrc8Nw0JsNjwCllOUdtwe3NuIx8oQuQ2fqj1G3g3xMp6B4sWBNAo+SjTNuKnS4chvbaD3RYnGvSLyNYu+sqbKeRNofCwVn0lVrjCAGtC9d5nqhFiGw0vWksPfmCRn7vRsl7LnqcXb+Fal/hhREBsaRJdMrst3vOEeQI6pt3RGKZ3VOsliNziKbLiNnXp2zY2fin32okAFwIOczPgeQA1yAM4FCnuT9FYAMn5ecAOY7WFhJPcOqVThy0giCJrBzpIzEHXTin+BWBO1PR8wMzBqpf6us9mhBZGzu40mzVN34xXK646aMr8f2DcD9yGO20v5icEz3OUcAeayMq+YKmBoypmvQUnaGa8pjr7RfvvajY+7pu6QHqRAQ3NLY1KjIoT3PKjabb7owQ1Txw5+Ajfjen7VEeF/Dq03nPMtNOpqD3tCdWDHWir+akJcEPtPzK4Bo2K3FrLBZt2igZD6/04jtwoAojHibKqUM1Rj5h2iijH65eAU1XKTpqDPNtcP5lwa1bFNV+GvuzHM+N4gcoxiELhQeG7xiUcsZrJvadkDO2z+If9vLkXTSdMKrqozUjLRapyXpULcVL8negHnj+2vKZVdoGiDhXlm23XDFjLY91ZqX2eGfGNmpJxftl83N6q4dyXpzD2gR/chHfm0CukVlL8P8aPAfEDcAsyQETc5oVLzetGVSkGBbQl+axZu8U2Ap9CXaTi1b2VcI3he19nvgG8XEFnwP6Tbicm5PDDsiRjo2MRqfuPLWkcSHTmBlS6w8yrzAvth9x/bBLg8XLs8M/B/dKSfOa9sbptfTMmEuuhWbnqCyqnFSUt8lsFlcUbJdK02TcMbd789pANnrKTTfFeOUehu5XReHng4DfV7f6boQmJPnZfwuR8qFwp7vwme235RTloktlkQu/2QFl2LmCv+/8Za43dEdFba9Ae6I1p+50zunyIjGTE6/9RT+g/zgagzgV/qDDSM5VF6E2Ic62W/KkpfSPMHAk5Jwg0LlsSMnFXYCynZoDZ5M8s62V15VaEII3s/6wPCu4lba/BxPanRtw60EVsvrJ7B0mnG+hcW8AGVeG1ZBIhgPH887/bY+05b0MnSkhjlrys8GKSaukVbtnrLJmjePt+LdLe6tH2NTwxjbHhJR028ZWaQKvdC5BD2hRflDMBPKL68D6YJ2bitqnKKdEqYHdCMXtOXh68XUqwfkoF3phQtYHyrqF4Wsgukf3/gAlt/yF0dXFTIUzoDTc34MEAaLFENVFDt4PUnYw2SRT8i/bhi3tcavu6Hnjs=";
    private static final String TN_BASE64 = "BMWDCPVx97y8KsnGiff6u4lmEogvgO30LtR/QvfGyqQWadycCGkbGhL7jCKvJTHmlK0k+fDR0XKq8U2IINpo0+aiWg8+nwaXQofOsilfXgDzG0DK9WJuwfcOrzGUHBn4yGVXDj+SUklPWbq0fojYGLYendkSnSLYTzeYIusMyZ3HD2djXyUvekKz0cp39JgrD/Ovj2Nrwn4ffPHcIXgSjpd02QXn4LNb4/7q465mfS2oQ5fRqiRMcnxpUhSD3Ty15bXVKJpPVqlqpM+tcUcXVV4g7ggOux361BsPius8as1vd7wuK44EOJ56MJeATqROjECur2bWdftoWydjfZj5sw==";
    
    // RSA私钥
    private static final String PRIVATE_KEY_PEM = 
        "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCz8JyumzBRR1nj" +
        "dxPzCFpqWXrAUBiC4ycTbTDdWdpZkciwiXU5s/OxF5i7l+Hvwc9Ggjph/PKo7PpW" +
        "hxZpzyEGpd6yVN9jAjJOt23o2TesgK8L/DAMhdJL8gNxKAQumbGF+ebMbcS8jWLx" +
        "vDAqpmnEW8VdCLEjF6uqOPtcDmIkBF83W6oaeu32DzTr/NS16sUGQKxlflo9qPOl" +
        "7VtcIsbR52klKK4uIyY23tWCouiyG84c/Uit+PleD5EYUGEu3p7IAAG5uJNzeUd0" +
        "UjZDhy6x7ue+kGgcCmCNQ4zSS/bQHMknalwqJUvUSxtIf8dq+/D78m7d4Zt9n9ZD" +
        "27t4Z2jHAgMBAAECggEAAr15RVdrpvE1NzeLADpyVghCzEbr+KJI6AzTn6tMneyQ" +
        "Z8/QDy7kWSAI3WJ0uFf1Nhepl/BoKZZiQYsRFk9nK1i/SWvtcu6HoZc9fzw/ksrq" +
        "333ZpXcsOqfW0ZRQa/0/LNEfaKGLS2vDw/afrSaXmbvkB4SoXeZwYMk5Wq+FYxL/" +
        "alrNpg/lzdvBlsCsTDA0G2RZrUVaO5yRTLRisBU+i8yORgnGkEwWvKpZYSFogCHS" +
        "iYHiNXFy//C+sYWlK7DjmG8/+krKhqBRRfdeg7LFThHQpbEGTtueD57jw0PCo2yr" +
        "6dqTvW9Qys+aWVNJk7RHNaI0yBFKWPadaHi3/olzkQKBgQDmz/FDpztS0fjKDIOj" +
        "gDyE76Z6dRFenmKJM1eOFt+MniY6/vi4ylU51/Etm4k6dNJ1MVBoFfyT9X0U/4k7" +
        "GNNUfIxMCJztUgY6EaCCt+09wk8pIvmOlRCmtxGwvmVC4nJVgUj3XJQ+wseblAkk" +
        "W0+IuT3GKX0CdKFMU4q9aucLYwKBgQDHk3rQ8Ae4ci4oj+MehRI29SNpcXG6OHbr" +
        "Z2EdsgqiFC1o/qv0269jtmCP7IqkGMdhTQrVetTHjZNZJH2bvUZ4o/0YT2+TTFPI" +
        "kTb2/a0txUTBTKrbnAdXh/iPFZAGvBROEDN0MNKo/vGAfi0K836DeTyBIaYongm6" +
        "6Rn6pwnUTQKBgBveVaougfoxAhIbSrWuISCH8xjsE6nSA+G/Aj5Uwq8u1TzgVlWx" +
        "kHLIgQVZt0sImfSufJ/kr7eJt42WgRJSoAmedC4mCBSbh8bxI+lEne+MC5TS9UDi" +
        "/Ly0c/1cL8vQna93ScEcO4YMbJ97U1NBdyvx+eR4U/C89lDJ8YGHa9gzAoGAQ6sY" +
        "sHFCXOKyDeTDoFyEUYgKqrzhT7/HaofR4Oy2OEBZKUl4anx2WnvC/+m3FG6mY7Jo" +
        "ovuT29mABXCe+khR9aO8tBpy/WGa4t2B4nse1e8WIehp4i5kOuSKfZFVFUN+Kv3J" +
        "RHMtakmO/v9JLHZlBhT8U9hh61GygOJ6gYdTiN0CgYAFz9iPy/xqLOUwiTNp3Imz" +
        "hdZo9ol3Qlr9CfMWMFHqRA5AyYvly9ZzxTpUCpSA+qz6OXqAjJ0bhGQxW2KHpmcT" +
        "yNGOPPca2vCaW8Mb1NTQueXpUBqX7alIkrRjUUyULteLb8FtyYl7mR3TVIu3FoO5" +
        "anNwDZ+2y7R9WUEiOzY3NA==";
    
    public static void main(String[] args) {
        printHeader("SO包加密逻辑完整验证");
        System.out.println("基于libsmsdk.so.c源代码分析，逐步验证加密流程");
        System.out.println("=".repeat(100));
        
        try {
            // ========================================
            // 步骤1: RSA解密ep字段
            // ========================================
            printStep(1, "使用RSA私钥解密ep字段（RSA-2048 NoPadding）");
            
            byte[] epEncrypted = Base64.getDecoder().decode(EP_BASE64);
            System.out.println("  ├─ ep密文长度: " + epEncrypted.length + " 字节");
            System.out.println("  ├─ ep密文(hex前32字节): " + bytesToHex(Arrays.copyOf(epEncrypted, 32)));
            
            // 加载RSA私钥
            byte[] privateKeyBytes = Base64.getDecoder().decode(PRIVATE_KEY_PEM);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            
            // RSA解密（NoPadding模式，与SO包一致）
            Cipher rsaCipher = Cipher.getInstance("RSA/ECB/NoPadding");
            rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] epDecrypted = rsaCipher.doFinal(epEncrypted);
            
            System.out.println("  ├─ ep解密后长度: " + epDecrypted.length + " 字节");
            System.out.println("  ├─ ep解密后完整内容(hex): " + bytesToHex(epDecrypted));
            System.out.println("  └─ ✓ RSA解密完成");
            
            // ========================================
            // 步骤2: 解析AES密钥结构
            // ========================================
            printStep(2, "解析ep结构（验证SO包分析：ep[0]=0x00, ep[1:33]=AES密钥）");
            
            System.out.println("  ├─ ep[0] = 0x" + String.format("%02x", epDecrypted[0]) + " (应为0x00)");
            
            if (epDecrypted[0] != 0x00) {
                System.out.println("  └─ ⚠ 警告: ep[0]不是0x00，尝试不同的解析方式...");
                // 可能是OAEP填充或其他情况
            }
            
            // 提取AES密钥（根据SO包分析，应该在ep[1:33]）
            byte[] aesKey = Arrays.copyOfRange(epDecrypted, 1, 33);
            System.out.println("  ├─ AES密钥(ep[1:33]): " + bytesToHex(aesKey));
            System.out.println("  ├─ AES密钥长度: " + aesKey.length + " 字节 (32字节=AES-256)");
            
            // 检查剩余部分
            byte[] padding = Arrays.copyOfRange(epDecrypted, 33, epDecrypted.length);
            System.out.println("  ├─ 填充数据长度: " + padding.length + " 字节");
            System.out.println("  ├─ 填充数据(hex前32字节): " + bytesToHex(Arrays.copyOf(padding, Math.min(32, padding.length))));
            System.out.println("  └─ ✓ AES密钥提取完成");
            
            // ========================================
            // 步骤3: 解密data字段
            // ========================================
            printStep(3, "AES-256-CBC解密data字段（IV前置）");
            
            byte[] dataWithIV = Base64.getDecoder().decode(DATA_BASE64);
            System.out.println("  ├─ data(Base64解码后)长度: " + dataWithIV.length + " 字节");
            
            // 提取IV（前16字节）
            byte[] dataIV = Arrays.copyOfRange(dataWithIV, 0, 16);
            System.out.println("  ├─ data的IV(前16字节): " + bytesToHex(dataIV));
            
            // 提取密文
            byte[] dataEncrypted = Arrays.copyOfRange(dataWithIV, 16, dataWithIV.length);
            System.out.println("  ├─ data密文长度: " + dataEncrypted.length + " 字节");
            
            // AES-256-CBC解密
            Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec aesKeySpec = new SecretKeySpec(aesKey, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(dataIV);
            aesCipher.init(Cipher.DECRYPT_MODE, aesKeySpec, ivSpec);
            byte[] dataCompressed = aesCipher.doFinal(dataEncrypted);
            
            System.out.println("  ├─ AES解密后长度: " + dataCompressed.length + " 字节");
            System.out.println("  ├─ 解密后数据(hex前32字节): " + bytesToHex(Arrays.copyOf(dataCompressed, Math.min(32, dataCompressed.length))));
            System.out.println("  └─ ✓ AES解密完成");
            
            // ========================================
            // 步骤4: zlib解压缩
            // ========================================
            printStep(4, "zlib解压缩（wbits=-15, RAW deflate格式）");
            
            System.out.println("  ├─ 压缩数据长度: " + dataCompressed.length + " 字节");
            
            // 使用Inflater解压（nowrap=true对应wbits=-15）
            Inflater inflater = new Inflater(true);  // true = nowrap mode (RAW deflate)
            inflater.setInput(dataCompressed);
            
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            while (!inflater.finished()) {
                int count = inflater.inflate(buffer);
                baos.write(buffer, 0, count);
            }
            inflater.end();
            
            byte[] decompressed = baos.toByteArray();
            System.out.println("  ├─ 解压后长度: " + decompressed.length + " 字节");
            System.out.println("  ├─ 压缩率: " + String.format("%.2f%%", (1 - (double)dataCompressed.length / decompressed.length) * 100));
            System.out.println("  └─ ✓ 解压缩完成");
            
            // ========================================
            // 步骤5: 解析设备信息JSON
            // ========================================
            printStep(5, "解析设备信息JSON");
            
            String deviceJson = new String(decompressed, StandardCharsets.UTF_8);
            System.out.println("  ├─ JSON长度: " + deviceJson.length() + " 字符");
            System.out.println("  ├─ JSON内容:");
            System.out.println("  │");
            
            // 格式化输出JSON（简单缩进）
            String[] lines = deviceJson.split("\n");
            for (String line : lines) {
                if (line.length() > 100) {
                    System.out.println("  │   " + line.substring(0, 100) + "...");
                } else {
                    System.out.println("  │   " + line);
                }
            }
            
            System.out.println("  │");
            System.out.println("  └─ ✓ 设备信息解析完成");
            
            // ========================================
            // 步骤6: 解密tn字段
            // ========================================
            printStep(6, "AES-256-CBC解密tn字段");
            
            byte[] tnWithIV = Base64.getDecoder().decode(TN_BASE64);
            System.out.println("  ├─ tn(Base64解码后)长度: " + tnWithIV.length + " 字节");
            
            // 提取IV
            byte[] tnIV = Arrays.copyOfRange(tnWithIV, 0, 16);
            System.out.println("  ├─ tn的IV(前16字节): " + bytesToHex(tnIV));
            
            // 提取密文
            byte[] tnEncrypted = Arrays.copyOfRange(tnWithIV, 16, tnWithIV.length);
            System.out.println("  ├─ tn密文长度: " + tnEncrypted.length + " 字节");
            
            // AES解密
            IvParameterSpec tnIvSpec = new IvParameterSpec(tnIV);
            aesCipher.init(Cipher.DECRYPT_MODE, aesKeySpec, tnIvSpec);
            byte[] tnDecrypted = aesCipher.doFinal(tnEncrypted);
            
            System.out.println("  ├─ tn解密后长度: " + tnDecrypted.length + " 字节");
            
            // ========================================
            // 步骤7: 解析tn内容
            // ========================================
            printStep(7, "解析tn字段内容");
            
            String tnContent = new String(tnDecrypted, StandardCharsets.UTF_8);
            System.out.println("  ├─ tn内容: " + tnContent);
            System.out.println("  └─ ✓ tn解析完成");
            
            // ========================================
            // 步骤8: 验证总结
            // ========================================
            printStep(8, "验证总结");
            
            System.out.println("  ✓ 所有步骤完成！验证结果：");
            System.out.println("  │");
            System.out.println("  ├─ [1] RSA-2048 NoPadding解密ep ✓");
            System.out.println("  ├─ [2] ep结构验证: ep[0]=0x" + String.format("%02x", epDecrypted[0]) + ", ep[1:33]=AES密钥 " + (epDecrypted[0] == 0 ? "✓" : "⚠"));
            System.out.println("  ├─ [3] AES-256-CBC解密data（IV前置）✓");
            System.out.println("  ├─ [4] zlib RAW deflate解压（wbits=-15）✓");
            System.out.println("  ├─ [5] 设备信息JSON解析 ✓");
            System.out.println("  ├─ [6] AES-256-CBC解密tn ✓");
            System.out.println("  └─ [7] tn内容解析 ✓");
            System.out.println("  │");
            System.out.println("  ══════════════════════════════════════════════════════════");
            System.out.println("  结论: SO包加密流程分析完全正确！");
            System.out.println("  ══════════════════════════════════════════════════════════");
            System.out.println("  │");
            System.out.println("  加密架构确认:");
            System.out.println("  ├─ 对称加密: AES-256-CBC (32字节密钥, 16字节IV)");
            System.out.println("  ├─ 非对称加密: RSA-2048 NoPadding");
            System.out.println("  ├─ 压缩算法: zlib deflate (level=9, wbits=-15)");
            System.out.println("  ├─ 编码方式: Base64 (标准字符集)");
            System.out.println("  └─ IV传输: IV前置（concat(IV, 密文)）");
            
        } catch (Exception e) {
            System.err.println("\n✗ 错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    private static void printHeader(String title) {
        System.out.println("\n" + "=".repeat(100));
        System.out.println("  " + title);
        System.out.println("=".repeat(100));
    }
    
    private static void printStep(int step, String description) {
        System.out.println("\n┌─────────────────────────────────────────────────────────────────────────────────────────────┐");
        System.out.println("│ 步骤 " + step + ": " + description);
        System.out.println("└─────────────────────────────────────────────────────────────────────────────────────────────┘");
    }
    
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}


